package com.cyb.myfriend.service.impl;

import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;


import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cyb.myfriend.constant.StatusCode;
import com.cyb.myfriend.constant.UserConstant;
import com.cyb.myfriend.domain.entity.User;
import com.cyb.myfriend.exception.BusinessException;
import com.cyb.myfriend.mapper.UserMapper;
import com.cyb.myfriend.service.UserService;
import com.cyb.myfriend.utils.PasswordManagerUtil;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import net.bytebuddy.description.method.MethodDescription;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;


/**
 * @author cyb
 * @date 2024/08/10 08:21
 **/
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    @Resource
    private UserMapper userMapper;

    @Override
    public int register(String userAccount, String userPassword, String exPassword) {
        //1. 校验
        //  a. 校验账户、密码是否为空
        if (StringUtils.isBlank(userAccount) || StringUtils.isBlank(userPassword) || StringUtils.isBlank(exPassword)) {
            throw new BusinessException(StatusCode.NULL_PARAMS);
        }
        //  b. 校验账户长度 >= 4
        //  c. 校验密码长度 >= 8
        if (userAccount.length() < 4 || userPassword.length() < 8 || exPassword.length() < 8) {
            throw new BusinessException(StatusCode.PARAMS_ERROR, "账户长度需大于四位, 密码大于8位");
        }
        //  d. 校验密码 是否 等于二次密码
        if (!userPassword.equals(exPassword)) {
            throw new BusinessException(StatusCode.PARAMS_ERROR, "输入的两次密码不一致");
        }
        //  e. 账户不能包含特殊字符
        if (!userAccount.matches(UserConstant.REGEX)) {
            throw new BusinessException(StatusCode.PARAMS_ERROR, "账户不能包含特殊字符");
        }
        //  f. 校验账户是否已经存在
        QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
        userQueryWrapper.eq("userAccount", userAccount);
        Long count = userMapper.selectCount(userQueryWrapper);
        if (count > 0) {
            throw new BusinessException(StatusCode.PARAMS_ERROR, "账户已存在！");
        }
        //2. 密码加密
        String hashPassword = PasswordManagerUtil.hashPassword(userPassword);
        //3. 向数据库中插入数据
        User user = new User();
        user.setUserAccount(userAccount);
        user.setUserPassword(hashPassword);
        user.setUserStatus(0);
        user.setCreateTime(new Date());
        user.setUpdateTime(new Date());
        user.setIsDelete(0);
        user.setUserRole(0);
        int result = userMapper.insert(user);
//        System.out.println(result);
        //4. 返回用户id
        return result;
    }

    @Override
    public User login(String userAccount, String userPassword, HttpServletRequest request) {
        //1. 校验
        //  a. 校验账户、密码是否为空
        //  b. 校验账户长度 >= 4
        //  c. 校验密码长度 >= 8
        //  d. 账户不能包含特殊字符
        if (StringUtils.isBlank(userAccount) || StringUtils.isBlank(userPassword)) {
            throw new BusinessException(StatusCode.NULL_PARAMS, "参数不能为空！");
        }
        if (userAccount.length() < 4 || userPassword.length() < 8) {
            throw new BusinessException(StatusCode.PARAMS_ERROR, "账户长度需大于四位, 密码大于8位");
        }
        if (!userAccount.matches(UserConstant.REGEX)) {
            throw new BusinessException(StatusCode.PARAMS_ERROR, "账户不能包含特殊字符");
        }
        //2. 查询用户是否存在
        //3. 判断密码是否一致
        QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
        userQueryWrapper.eq("userAccount", userAccount);
        User user = userMapper.selectOne(userQueryWrapper);
        if (user == null) {
            throw new BusinessException(StatusCode.NO_USER, "用户不存在！");
        }
        boolean is_equals = PasswordManagerUtil.checkPassword(userPassword, user.getUserPassword());
        if (!is_equals) {
            throw new BusinessException(StatusCode.PARAMS_ERROR, "密码不正确！");
        }
        //5. 若存在返回用户信息(脱敏)
        User safetyUser = getSafetyUser(user);
        //4. 记录用户的登录态（session）
        request.getSession().setAttribute("userLoginState", safetyUser);
        return safetyUser;
    }

    @Override
    public int saveUser(User user, HttpServletRequest request) {
        if (user == null) {
            throw new BusinessException(StatusCode.NULL_PARAMS, "参数不能为空！");
        }
        // 校验是否为管理员角色
        User userLoginState = (User) request.getSession().getAttribute("userLoginState");
        if (userLoginState == null) {
            throw new BusinessException(StatusCode.NO_LOGIN, "用户未登录！");
        }
        if (userLoginState.getUserRole() != UserConstant.ADMIN_ROLE) {
            throw new BusinessException(StatusCode.NO_AUTH, "用户无权限！");
        }
        QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
        userQueryWrapper.eq("userAccount", user.getUserAccount());
        Long count = userMapper.selectCount(userQueryWrapper);
        if (count > 0) {
            throw new BusinessException(StatusCode.PARAMS_ERROR, "账户已存在！");
        }
        // 密码加密
        String userPassword = user.getUserPassword();
        String hashPassword = PasswordManagerUtil.hashPassword(userPassword);
        user.setUserPassword(hashPassword);
        int insertResult = userMapper.insert(user);
        if (insertResult < 1) {
            throw new BusinessException(StatusCode.OPERATION_ERROR, "添加用户失败");
        }
        return insertResult;
    }

    @Override
    public int deleteUser(User user, HttpServletRequest request) {
        if (user == null || user.getId() == null) {
            throw new BusinessException(StatusCode.NULL_PARAMS, "参数不能为空！");
        }
        User userLoginState = (User) request.getSession().getAttribute("userLoginState");
        if (userLoginState == null) {
            throw new BusinessException(StatusCode.NO_LOGIN, "用户未登录！");
        }
        if (userLoginState.getUserRole() < UserConstant.ADMIN_ROLE) {
            throw new BusinessException(StatusCode.NO_AUTH, "用户无权限！");
        }
        int deleteResult = userMapper.deleteById(user.getId());
        if (deleteResult < 1) {
            throw new BusinessException(StatusCode.OPERATION_ERROR, "删除用户失败");
        }
        return deleteResult;
    }

    @Override
    public int updateUser(User user, HttpServletRequest request) {
        if (user == null || user.getId() == null) {
            throw new BusinessException(StatusCode.NULL_PARAMS, "参数不能为空！");
        }
        User userLoginState = (User) request.getSession().getAttribute("userLoginState");
        if (userLoginState == null) {
            throw new BusinessException(StatusCode.NO_LOGIN, "用户未登录！");
        }
        if (userLoginState.getUserRole() < UserConstant.ADMIN_ROLE) {
            throw new BusinessException(StatusCode.NO_AUTH, "用户无权限！");
        }
        int updateResult = userMapper.updateById(user);
        if (updateResult < 1) {
            throw new BusinessException(StatusCode.OPERATION_ERROR, "更新用户失败");
        }
        return updateResult;
    }

    @Override
    public User selectUser(User user, HttpServletRequest request) {
        if (user == null || user.getId() == null) {
            throw new BusinessException(StatusCode.NULL_PARAMS, "参数不能为空！");
        }
        User userLoginState = (User) request.getSession().getAttribute("userLoginState");
        if (userLoginState == null) {
            throw new BusinessException(StatusCode.NO_LOGIN, "用户未登录！");
        }
        if (userLoginState.getUserRole() < UserConstant.ADMIN_ROLE) {
            throw new BusinessException(StatusCode.NO_AUTH, "用户无权限！");
        }
        User selectUser = userMapper.selectById(user.getId());
        if (selectUser == null) {
            return null;
        }
        // 脱敏
        User safetyUser = getSafetyUser(selectUser);
        return safetyUser;
    }


    @Override
    public List<User> selectAllUser(HttpServletRequest request) {
        User userLoginState = (User) request.getSession().getAttribute("userLoginState");
        if (userLoginState == null) {
            throw new BusinessException(StatusCode.NO_LOGIN, "用户未登录！");
        }
        if (userLoginState.getUserRole() < UserConstant.ADMIN_ROLE) {
            throw new BusinessException(StatusCode.NO_AUTH, "用户无权限！");
        }
        QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
        List<User> userList = userMapper.selectList(userQueryWrapper);
        return userList;
    }

    /**
     * 基于SQL实现
     *
     * @param tagList 标签列表
     * @return 完全匹配标签的用户
     */
    @Override
    public List<User> selectUserByTagsToSQL(List<String> tagList) {
        if (CollectionUtils.isEmpty(tagList)) {
            throw new BusinessException(StatusCode.PARAMS_ERROR);
        }
        QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
        for (String tagName : tagList) {
            if (StringUtils.isBlank(tagName)) {
                continue;
            }
            userQueryWrapper = userQueryWrapper.like("tags", tagName);
        }
        // todo 传入"" 会查询所有，而我这个功能是完全匹配
        List<User> userList = userMapper.selectList(userQueryWrapper);
        // 脱敏
        return userList.stream().map(this::getSafetyUser).collect(Collectors.toList());
    }

    /**
     * 基于内存实现
     *
     * @param tagList 标签列表
     * @return 完全匹配标签的用户
     */
    @Override
    public List<User> selectUserByTagsToMemory(List<String> tagList) {
        if (CollectionUtils.isEmpty(tagList)) {
            throw new BusinessException(StatusCode.PARAMS_ERROR);
        }
        // 先查询所有用户
        QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
        List<User> userList = userMapper.selectList(userQueryWrapper);
        // 在内存中进行匹配
        Gson gson = new Gson();
        return userList.stream().filter(user -> {
            // 拿到用户标签
            String tmpTagList = user.getTags();
            // 将json转化为set集合
            Set<String> userTagSet = gson.fromJson(tmpTagList, new TypeToken<Set<String>>(){}.getType());
            if (userTagSet.isEmpty()) {
                return false;
            }
            // 挨个匹配
            for (String tagName : tagList) {
                if (!userTagSet.contains(tagName) || StringUtils.isBlank(tagName)) {
                    return false;
                }
            }
            return true;
        }).collect(Collectors.toList());
    }


    /**
     * 用户信息脱敏
     *
     * @param user 用户信息
     * @return 脱敏用户信息
     */
    private User getSafetyUser(User user) {
        User safetyUser = new User();
        safetyUser.setId(user.getId());
        safetyUser.setUsername(user.getUsername());
        safetyUser.setUserAccount(user.getUserAccount());
        safetyUser.setAvatarUrl(user.getAvatarUrl());
        safetyUser.setGender(user.getGender());
        safetyUser.setPhone(user.getPhone());
        safetyUser.setEmail(user.getEmail());
        safetyUser.setUserStatus(user.getUserStatus());
        safetyUser.setCreateTime(user.getCreateTime());
        safetyUser.setUpdateTime(user.getUpdateTime());
        safetyUser.setUserRole(user.getUserRole());
        safetyUser.setTags(user.getTags());
        return safetyUser;
    }
}




